#!/usr/bin/env python2
# -*- coding: utf-8 -*-

import json
import traceback
import sys
from pprint import pprint
import threading


from Ump.common import log
from Ump.common import config
from Ump.common import jsonobject
from Ump.common.remote import _exec_remote
from Ump.common.utils import package_error, inspect_func
from Ump import utils
from Ump.objs.session_wrapper import _sw

from Ump import utils, defs
from agentapi import cmd as cmd_api 


LOG = log.init_info_logger()

NO_LICH_CODE = 'lich code not exist'

class RemoteLocation(object):

    @inspect_func
    def __init__(self, host_ip=None, cluster_id=1, username='root', password='mdsmds'):
        lich = LichBase()
        if not host_ip:
            if not cluster_id:
                cluster_id = 1
            host_ip = lich._select_http(cluster_id=cluster_id)
        self.host_ip = host_ip
        self.username = username
        self.password = password


class LichSetting(object):
    def __init__(self):
        self.lich_home = config.lich_home


class LichBase(object):
    def __init__(self, _sw=None):
        self.settings = LichSetting()
        self.is_fusionnas = defs.PRODUCT_NAME == 'fusionnas'

        self.lich_home = self.settings.lich_home
        if self.is_fusionnas:
            self.lich_home = '/opt/fusionnas'


        # commands
        self.lich = '%s/lich/admin/cluster.py' % self.lich_home
        self.lich_cluster = '%s/lich/admin/cluster.py' % self.lich_home
        self.lich_node = '%s/lich/admin/node.py' % self.lich_home
        self.lichfs = '%s/lich/libexec/lichfs' % self.lich_home
        self.lichbd = '%s/lich/libexec/lichbd' % self.lich_home
        self.lich_snapshot = '%s/lich/libexec/lich.snapshot' % self.lich_home
        self.lich_inspect = '%s/lich/libexec/lich.inspect' % self.lich_home
        self.lich_admin = '%s/lich/libexec/lich.admin' % self.lich_home

        self.lich_license = '%s/lich/libexec/lich.license' % self.lich_home
        if self.is_fusionnas:
           self.lich_license = '/opt/fusionnas/app/bin/uss.license' 
        self.lich_syncump = '%s/lich/admin/syncump.py' % self.lich_home
        self.storagent_port = config.storagent_port


        self._execute_remote = _exec_remote

    def _select_host(self, cluster_id=1, is_hostname=False):
        return self.__select_host(cluster_id, is_hostname, ishttp=False)

    def _select_http(self, cluster_id=1):
        return self.__select_host(cluster_id, ishttp=True)

    def __select_host(self, cluster_id, is_hostname=False, ishttp=False):
        cluster = _sw.db_cluster(cluster_id)
        if not cluster :
            raise Exception('cluster can not be None')

        hosts = cluster.hosts
        if hosts == []:
            raise Exception('您的集群还没有添加节点，请添加节点后操作')

        hostnames = [host.name for host in hosts]
        host_ip = hostname = None
        for host in hosts:
            if host.is_host_deleting:
                continue

            if host.status == 'joining':
                continue

            try:
                hostname = self.test_agent_node_avail(host, ishttp=ishttp)
                host_ip = host.ip
            except Exception, e:
                print ("select_available_host ERROR:test host %s:%s" % (host.ip, e))
                LOG.info("select_available_host ERROR:test host %s:%s" % (host.ip, e))

            if hostname and NO_LICH_CODE in hostname:
                continue

            if host_ip is not None:
                break

        if host_ip is None :
            [host.update({'status':'shutdown'}) for host in cluster.hosts]
            raise Exception('not find avalible agent node')

        if is_hostname:
            return host_ip, hostname
        else:
            return host_ip

    def test_agent_node_avail(self, host, ishttp=False):
        cmd = "hostname;if [ ! -f %s ];then echo '%s'; fi" % (self.lich, NO_LICH_CODE)
        if ishttp:
            hostname = self.api_sync_call(host.ip, cmd, timeout=10)
        else:
            hostname = _exec_remote(host.ip, cmd)
        hostname = hostname.strip()
        return hostname

    @inspect_func
    def api_sync_call(self, host_ip, cmd, cluster_id=None, timeout=300):
        if cluster_id:
            host_ip, hostname = self._select_host(cluster_id, is_hostname=True)
        if 'allocate' in cmd:
            timeout = 6*60*60

        if 'cluster.py create' in cmd:
            timeout = 2*60*60

        if not host_ip:
            LOG.error("%s no target host" % (msg.get('cmd')))
            raise Exception(u"no target host for agent")

        cmd_obj = cmd_api.CmdExecuteCmd()
        cmd_obj.host = host_ip
        cmd_obj.cmd = cmd
        return self._http_request(cmd_obj, host_ip, timeout=timeout)


    def _http_request(self, cmd_obj, host_ip, timeout=300, is_raise=True):
        try:
            response = utils._exec_http(cmd_obj, host_ip, self.storagent_port, timeout=timeout)
            cmd = cmd_obj.cmd
            returncode = response.returncode
            stderr = response.stderr
            stdout = response.stdout
            if cmd_obj.cmd.find('listnode') != -1:
                stdout = stdout +'\n'+ stderr
            if 'uss.license' in cmd or 'lich.license' in cmd:
                is_raise = False
                stdout = stdout +'\n'+ stderr

            if returncode not in [0, '0'] and is_raise:
                log_str = '%s-%s:%s:%s' % (host_ip, cmd, returncode, stderr)
                LOG.error(log_str)
                package_error(returncode, stderr, cmd)
                raise Exception('%s' % (stderr))

            log_str = '%s-%s:%s:%s' % (host_ip, cmd, returncode, stdout)
            LOG.info(log_str)
        except Exception as e:
            #traceback.print_exc()
            raise Exception('http request fail:%s :%s' % (host_ip, e))
        return stdout


if __name__ == '__main__':
    lich = LichBase()
    print lich._select_http()
